<!DOCTYPE html>
<html>

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>HCEmrViewLib Demo</title>
    <script type="text/javascript" src="./HCEmrViewLib.min.js"></script>
    <script type="text/javascript">
        var TItemStyle = {
            Null: -1,
            Image: -2,  // 图片
            Table: -3,  // 表格
            Tab: -4,  // TAB键
            Line: -5,  // 直线
            Express: -6,  // 公式
            Vector: -7,  // 矢量图
            Domain: -8,  // 域
            PageBreak: -9,  // 分页
            CheckBox: -10,  // 勾选框
            Gif: -11,  // GIF动画
            Control: -12,  // 控件
            Edit: -13,  // Edit 文本框
            Combobox: -14,  // Combobox 下拉弹出框
            QRCode: -15,  // 二维码
            BarCode: -16,  // 一维码
            Fraction: -17,  // 分数
            DateTimePicker: -18,  // 日期时间控件
            RadioGroup: -19,  // RadioGroup 单选、多选控件
            SupSubScript: -20,  // 同时上下标
            Button: -21,  // 按钮控件
            FloatLine: -101,  // 浮动直线
            FloatBarCode: -102,  // 浮动一维码
            Custom: -1000
        }

        // 数据元属性
        var TDeProp = {
            Index: "Index",  // 唯一索引
            Code: "Code",  // 编码
            Name: "Name",  // 名称
            Frmtp: "Frmtp",  // 类别，见TDeFrmtp枚举
            Unit: "Unit",  // 单位
            HideUnit: "HdUnit",  // 是否隐藏单位，比如血压的收缩压不显示单位
            PreFormat: "PRFMT",  // 表示格式
            Raw: "Raw",  // 原始数据
            CMV: "CMV",  // 受控词汇表(值域代码)
            CMVVCode: "CMVVCode",  // 受控词汇编码(值编码)
            Trace: "Trace",  // 痕迹信息
            /** * 删除痕迹信息 */
            TraceDel: "TcDel",
            /** * 添加痕迹信息 */
            TraceAdd: "TcAdd",
            /** * 删除痕迹的级别 */
            TraceDelLevel: "TcDelL",
            /** * 添加痕迹的级别 */
            TraceAddLevel: "TcAddL",
            Secret: "Secret",  // 是否属于隐私信息
            ItemEditValue: "EdtVal"  // 选项值直接编辑，不通过弹出框处理
        }

        // 数据元类型
        var TDeFrmtp = {
            Radio: "RS",  // 单选
            Multiselect: "MS",  // 多选
            Number: "N",  // 数值
            String: "S",  // 文本
            Date: "D",  // 日期
            Time: "T",  // 时间
            DateTime: "DT"  // 日期和时间
        }

        // 痕迹样式
        var TDeTraceStyle = {
            Del: 1, // 删除
            Add: 2, // 添加
            Mod: 4  // 修改
        }

        // 痕迹级别
        var TDeTraceLevel = {
            /** * 无医师级别 */
            None: "",
            /** * 住院医师 */
            One: "1",
            /** * 主治医师 */
            Two: "2",
            /** * 主任医师 */
            Three: "3"
        }

        var TGroupProp = {
            Index: "Index",
            Name: "Name",
            Code: "Code",
            SubType: "RT",
            Propertys: "Propertys"
        }

        var emrView;

        function appendLine(s) {
            var textArea = document.getElementById("textBox");
            if (textArea)
                textArea.value += "\r\n" + s;
        }

        function getBase64ByUrl (src, callback, outputFormat) {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", src, true);

            xhr.responseType = "arraybuffer";

            xhr.onload = function(e) {
                if (xhr.status == 200) {
                    var uInt8Array = new Uint8Array(xhr.response);
                    var i = uInt8Array.length;
                    var binaryString = new Array(i);
                    while (i--)
                        binaryString[i] = String.fromCharCode(uInt8Array[i]);

                    var data = binaryString.join('');
                    var base64 = window.btoa(data);
                    var dataUrl = "data:" + (outputFormat || "image/png") + ";base64," + base64;
                    callback.call(this, dataUrl);
                }
            }

            xhr.send();
        }

        function getFileAsBytes(src, callback) {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", src, true);
            xhr.responseType = "arraybuffer";
            xhr.onload = function(e) {
                if (xhr.status == 200) {
                    var vBytes = new Uint8Array(xhr.response);
                    callback.call(this, vBytes);
                }
            }

            xhr.send();
        }

        function load() {
            emrView = new THCEmrViewLib({
                debug: true,  // 使用debug模式，会显示一些日志
                //hcServer: "http://127.0.0.1:12880/",  // HC服务端IP
                hcServer: "http://123.206.99.69:12880/",
                baseUrl: "./",  // 编辑器需要的资源路径
                el: "divHCEmrView",  // 编辑器父容器的ID
                defaultFontSize: "小四",  // 编辑器默认字号，默认小四
                defaultFontFamily: "宋体",  // 编辑器默认字体，默认宋体
                paperSize: "A4",  // 纸张大小
                paperOrientation: 0,  // 纸张方向 0纵向 1横向，默认0
                designMode: false,  // 是否设计模式，也可以使用emrView.designMode = true;
                //multItemSpliter: "；",  // 多选选项之间的分隔符号
                //此属性已经不存在multItemEditValue: true,  // 多选数据元选项上屏后，再次点击直接编辑内容，使用右键菜单重新选择
                //deUnDoneColor: "#FF8C00",  // 没选过选项或没写过内容时数据元背景色
                //deDoneColor: "#AFEEEE",  // 填写或选择过选项的数据元背景色
                //deHotColor: "#87CEFA",  // 鼠标移动上去时的颜色
                //traceInfoAnnotate: true,  // 痕迹以批注形式显示
                
                //useAnnotate: false,  // 允许使用批注
                //showExportMenu: true,  // 显示导出文件菜单
                //showImportMenu: true,  // 显示导入文件菜单

                // 工具条
                toolBar: {
                    visible: true,  // 是否整体显示顶部工具条，也可以使用emrView.toolBar.visible = false;
                    //height: 35,  // 设置工具栏高度
                    // 文件按钮
                    btnFile: {
                        visible: 1
                    },

                    // 打印按钮
                    btnPrint: {
                        visible: true,
                    },

                    // 外部自定义按钮
                    btnCustoms: [
                        {
                            text: "自定义",
                            image: "./image/file.png",
                            exec: function() {
                                //alert("点击了自定义按钮");
                                alert(emrView.SaveToText());
                            }
                        }
                    ]
                },

                // 右键菜单中添加自定义菜单
                contextMenu: [
                    {
                        text: "添加诊断",  // 菜单名
                        // 菜单点击事件
                        exec: function() {
                            appendLine("点击了菜单:添加诊断");
                            //emrView.InsertText("诊断内容");
                        },
                    },

                    {
                        text: "插入数据从HIS",
                        exec: function() { appendLine("点击了菜单:插入数据从HIS"); },

                        // 子菜单
                        subMenu: [
                            {
                                index: "2-1",
                                text: "插入检查",
                                exec: function() {
                                    appendLine("点击了菜单:插入检查");
                                    emrView.InsertText("检查内容");
                                },
                            },

                            {
                                text: "插入医嘱",
                                exec: function() {
                                    appendLine("点击了菜单:插入医嘱");
                                    emrView.InsertText("医嘱内容");
                                },
                            }
                        ]
                    }
                ],

                // 事件
                event: {
                    // 编辑器状态变化时触发：从未修改状态变为修改状态，或从修改状态变为未修改状态，
                    onChangedSwitch: function() {
                        if (emrView.IsChanged)
                            appendLine("onChangedSwitch 文档状态变为修改");
                        else
                            appendLine("onChangedSwitch 文档状态变为未修改");
                    },

                    onCaretItemChanged: function() {
                        appendLine("光标位置变动");
                        //if (emrView.CaretProcInfo.Index != emrView.EditProcIndex)
                        //    emrView.EditProcIndex = emrView.CaretProcInfo.Index;
                    },

                    // 点击了编辑器工具栏上的保存按钮时触发
                    onSave: function() {
                        appendLine("onSave 事件触发");
                        emrView.IsChanged = false;
                    },

                    // 鼠标点击数据元触发，如果数据元的信息有变化，可以这里重新赋值
                    onPopupGetDeItemInfo: function(item) {
                        appendLine("onPopupGetDeItemInfo 点击数据元触发 参数：{" + item.ToJSONString() + "}");
                        if (item.Index == "495") {  // 性别
                            // 点击数据元时，给数据元通过item.Index重新同步最新信息的机会，响应此事件，需要返回frmtp，数值类的需要返回单位deunit，单选多选要返回选项值域domainid
                            item.SetValue(TDeProp.Frmtp, TDeFrmtp.Radio);
                            item.SetValue(TDeProp.CMV, "271");  // 值域，271是数据库里性别元素的值域代码，实际可以通过e.index判断是哪个数据元，返回类别，如果是单选或多选类型同时要返回值域
                            
                            //item.SetValue(TDeProp.Frmtp, TDeFrmtp.Number);  // 类别，RS:单选 MS:多选 N:数值 S:文本 D:日期 T:时间 DT:日期时间
                            //item.SetValue(TDeProp.Unit, "岁,月,天,小时");  // 数值类的要传递单位
                        }
                    },

                    // 单选或多选数据元获鼠标点击后，显示选项时触发，可在这里把选项传递到编辑器中
                    onPopupGetDeItemDomain: function(cmv) {
                        appendLine("onPopupGetDeItemDomain 选项类数据元点击时请求选项 参数：" + cmv);
                        if (cmv == 271) {  // 值域ID,271是性别值域ID
                            var vs = '{"cv": [{"value": "男性", "code": "1", "id": 3681, "py": "NX", "content": ""},'
                                + '{"value": "女性", "code": "2", "id": 3682, "py": "NX", "content": ""},'
                                + '{"value": "未知（描述原因）", "code": "9", "id": 3683, "py": "WZ", "content": "..."}'
                                + ']}';
                            return JSON.parse(vs);
                        } else if (cmv == 299) {
                            var vs = '{"cv": [{"value": "静脉无曲张60", "code": "20", "id": 60, "py": "JMWQZ", "content": "..."},'

                            + '{"value": "静脉无曲张61", "code": "21", "id": 61, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张62", "code": "22", "id": 62, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张63", "code": "23", "id": 63, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张64", "code": "24", "id": 64, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张65", "code": "25", "id": 65, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张66", "code": "26", "id": 66, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张67", "code": "27", "id": 67, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张68", "code": "28", "id": 68, "py": "JMQZ", "content": "..."},'
                            + '{"value": "静脉无曲张69", "code": "29", "id": 69, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张70", "code": "30", "id": 70, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉无曲张71", "code": "31", "id": 71, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张72", "code": "32", "id": 72, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张73", "code": "33", "id": 73, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张74", "code": "34", "id": 74, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张75", "code": "35", "id": 75, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张76", "code": "36", "id": 76, "py": "JMQZ", "content": ""},'
                            + '{"value": "静脉有曲张77", "code": "37", "id": 77, "py": "JMQZ", "content": ""}'
                            + ']}';
                            return JSON.parse(vs);
                        } else if (cmv == 272) {
                            var vs = '{"cv": [{"value": "皮疹", "code": "1", "id": 689, "py": "PZ", "content": ""},'
                                + '{"value": "皮下出血", "code": "2", "id": 690, "py": "PZCX", "content": ""}'
                                + ']}';
                            return JSON.parse(vs);
                        }
                        // else if (emrView.HCServer) {  // 可请求HC服务端测试一下返回的选项
                        //     var vJSON;
                        //     var xhr = new XMLHttpRequest();
                        //     xhr.open("GET", emrView.HCServer + '?CMD="0"', false);
                        //     xhr.onload = function(e) {
                        //         if (xhr.status == 200) {
                        //             var vS = xhr.response;
                        //             vJSON = JSON.parse(vS);
                        //         }
                        //     }

                        //     xhr.send();
                        //     return vJSON;
                        // }
                    },

                    // 数据元选项有扩展内容时，获取扩展内容
                    onPopupGetDomainItemExtraLib: function(item, cvvid) {
                        if (item.Index == 499) {  // 数据元499，选择了带扩展内容的
                            if (cvvid == 68 || cvvid == 60) {  // 68的扩展内容
                                if (vBytes)
                                    emrView.SetActiveItemExtraByBytes(vBytes);
                            }
                        }
                    },

                    // 当编辑器在加载文档或插入了新的Item时触发，便于外部替换数据元的值，注意在加载普通的已经保存过的病历时也会触发此事件
                    // 所以给编辑器赋值此事件的合适的时机是：第一次加载模板之前；或打开已经保存过的病历之后；
                    onInserItemSync: function(sender, data, item) {
                        if (item.StyleNo > TItemStyle.Null && item.Index == "494") {  // item是姓名
                            item.Text = "张三";
                            item.AllocValue = true;  // 该元素填写过值了
                        } else if (item.StyleNo == TItemStyle.DateTimePicker) {  // 日期时间控件

                        }
                    },

                    // 当编辑器中的Combobox控件点击了下拉按钮，显示选项时触发
                    onDeComboboxPopup: function(cmbxItem) {
                        if (cmbxItem.Index == 495) {  // 是性别
                            if (!cmbxItem.SaveItem) {  // combobox自己没有保存选项
                                if (cmbxItem.Items.count > 0)
                                    cmbxItem.Clear();

                                cmbxItem.AddItem("男", "1");
                                cmbxItem.AddItem("女", "2");
                            }
                        }
                    },

                    // 判断当前情况下是否能编辑，此事件在引起内容变化的时候触发，较频繁，所以不要写复杂的业务
                    onCanEdit: function(data) {
                        // if (emrView.EditProcIndex != "")  // 当前指定了要编辑的病程
                        //     return emrView.CaretProcInfo.Index == emrView.EditProcIndex;  // 光标所在病程和当前允许编辑的病程Index相同
                        // else
                            return true;
                    },

                    // 选项类数据元在请求数据元信息和选项信息之前触发
                    onDeItemPopup: function(item) {
                        return true;
                    },

                    // 数据元右键菜单中的 更新引用 点击后触发的事件
                    onDeItemGetSyncValue: function(item) {
                        if (item.Index == "494")  // 姓名
                            return "李四福";
                    },

                    // 用户自定义打印过程，用于在打印前判断，并决定是否回调继续打印
                    // 注意不要在此事件里修改病历内容
                    // printType：打印类型，0打印全部或1-n页，1按行续打，2选中范围续打
                    // printFun：回调方法，调用表示继续打印
                    onPrintProcess: function(printType, printFun) {
                        printFun();
                    },

                    // 点了打印并在浏览器里显示了要打印的文件
                    onPrinted: function(type) {
                        // type 0打印全部或1-n页，1按行续打，2选中范围续打
                        console.log(type == 0 ? "打印" : "续打");
                    },

                    // 在编辑区域按键事件
                    // onEmrViewKeyDown: function(e) {
                    //     appendLine("编辑区按键 键值" + e.keyCode);
                    //     if (emrView.HCL.keyDownStates[17]  // 判断Ctrl是否按下，17为Ctrl键键值
                    //         && e.keyCode == 114)  // 114为 F3 的键值
                    //         emrView.NextDeItemAutoComplate();  // 自动打开下一个数据元的弹出框
                    // },

                    // 在整个编辑器UI区域按键事件，如果在这里响应了按键，最好有e.keyCode = 0;来停止按键事件往编辑区传递
                    onKeyDown: function(e) {
                        appendLine("编辑区按键 键值" + e.keyCode);
                        if (//emrView.HCL.keyDownStates[17]  // 判断Ctrl是否按下，17为Ctrl键键值
                            //&& 
                            e.keyCode == 114)  // 114为 F3 的键值 71为G键值
                        {
                            e.keyCode = 0;  // 停止按键事件往编辑区传递
                            emrView.NextDeItemAutoComplate();  // 自动打开下一个数据元的弹出框
                        }
                    },

                    // 编辑器初始化完成后触发的事件
                    onInitialization: function() {
                        appendLine("编辑器初始化完成！");
                    },

                    // 改变事件
                    onChange: function() {
                        appendLine("内容改变！");
                    },

                    // 编辑器双击事件
                    onDblClick: function() {
                        var deGroupInfo = emrView.GetCaretDeGroupProperty(TDeProp.Index);
                        if (deGroupInfo != "")
                            appendLine("编辑器双击事件onDblClick 光标处数据组：" + deGroupInfo);
                        else
                            appendLine("编辑器双击事件onDblClick");
                    },

                    // 鼠标弹起事件
                    onMouseUp: function(e, item) {
                        appendLine("鼠标弹起事件！");
                        if (emrView.HCL.keyDownStates[17]  // ctrl键按下
                            && (item.HyperLink != ""))  // 链接不为空
                            //window.open(item.HyperLink);  // 跳转到链接
                            window.location.href = item.HyperLink;
                    },

                    onViewMenuPopup: function(menus) {
                        for (var i = 0; i < menus.count; i++) {
                            if (menus[i].tag == 1) {  // 是自定义添加的菜单
                                if (menus[i].text == "添加诊断")
                                    menus[i].enabled = emrView.EditProcIndex == emrView.CaretProcInfo.Index;
                                else if (menus[i].text == "插入数据从HIS") {
                                    for (var j = 0; j < menus[i].subItems.count; j++) {  // 遍历下一级菜单
                                        if (menus[i].subItems[j].text == "插入医嘱")
                                            menus[i].subItems[j].visible = emrView.EditProcIndex == emrView.CaretProcInfo.Index;
                                    }
                                }
                            }
                        }
                    },

                    onSetDeItemText: function(item, text) {
                        if (item.Index == "341") {  // 体温
                            var vT = text.replace(new RegExp(item.GetValue(TDeProp.Unit), "g"), "");  // 体温值去掉单位
                            var vN = parseFloat(vT);
                            item.OutOfRang = (vN < 35 || vN > 37.3);
                        }
                    }
                }
            });

            // 向工具栏中添加按钮
            // emrView.AddToolButton(
            //     [
            //         {
            //             text: "自定义",
            //             exec: function() {
            //                 alert("点击了自定义按钮2");
            //             }
            //         }
            //     ]
            // );

            // 向编辑器的右键菜单中添加菜单
            // emrView.AddContextMenu(
            //     [
            //         {
            //             text: "添加菜单一",
            //             exec: function() {
            //                 appendLine("点击了菜单:添加菜单一");
            //             },

            //             // 子菜单
            //             subMenu: [
            //                 {
            //                     text: "子菜单一",
            //                     exec: function() {
            //                         appendLine("点击了菜单:子菜单一");
            //                     },
            //                 },

            //                 {
            //                     text: "子菜单二",
            //                     exec: function() {
            //                         appendLine("点击了菜单:子菜单二");
            //                     },
            //                 }
            //             ]
            //         }
            //     ]
            // );

            // 插入普通文本
            emrView.InsertText("姓名：");

            // 插入性别数据元，如果有赋值onInserItemSync方法，会在其中替换为实际的患者姓名
            var vDeItem = emrView.InsertDeItem({
                Index: "494",
                Name: "姓名",
                Frmtp: TDeFrmtp.String
            });
            //vDeItem.SetValue();  // 设置数据元的属性

            // 插入DeCombobox示例
            var vDeCombobox = emrView.InsertDeCombobox({
                Index: "495",
                Name: "性别",
                Static: true,  // 是否只能通过选项赋值(不能输入内容)，true是，false否
                ReadOnly: false,  // 是否只读，只读后不能修改内容
                SaveItem: true,  // 是否保存选项(保存选项会增加文件体积)
                PrintOnlyText: true,  // 打印时只打印文字，不打印按钮
                Items: [  // 插入时添加选项，注意如果要将选项保存到病历文件中，需要设置vDeCombobx.SaveItem = true;
                    {
                        Text: "男性",
                        TextValue: "1",
                        Checked: true,
                    },

                    {
                        Text: "女性",
                        TextValue: "2",
                        Checked: false,
                    },
                ]
            });

            // 插入RadioGroup示例
            var vDeRadioGroup = emrView.InsertDeRadioGroup({
                Index: "495",
                Name: "性别",
                Style: "Radio",  // Radio:圆点 CheckBox:勾选
                MultSelect: "0",  // 单选or多选 0单选 1多选
                AutoSize: false,  // 根据内容自动计大小
                Columes: 2,  // 以几列显示
                ColumnAlign: true,  // 列自动对齐
                ItemHit: true,  // 点击文件就算选中 false点击圆点或勾选框才算选中

                Width: 300,
                Items: [  // 选项
                    {
                        Text: "未知的性别",
                        TextValue: "0",
                        Checked: false,
                    },

                    {
                        Text: "男",
                        TextValue: "1",
                        Checked: true,
                    },

                    {
                        Text: "女",
                        TextValue: "2",
                        Checked: false,
                    },

                    {
                        Text: "未说明的性别",
                        TextValue: "9",
                        Checked: false,
                    }
                ]
            });

            // 插入表格示例
            var vDeTable = emrView.InsertDeTable({
                BorderVisible: false,
                RowCount: 3,
                ColCount: 3,
                ColWidths: [200, "15%"],
                Rows: [  // 行s
                    {  // 第1行
                        Cells: [  // 列s
                            {  // 第1列
                                Text: "第一行第一列"
                            },
                            {

                            },
                            {
                                Text: "第一行第三列"
                            }
                        ]
                    },

                    {

                    },

                    {
                        Cells: [
                            {
                                Text: "第三行第一列"
                            }
                        ]
                    }
                ]
            });

            // 插入数据元
            var vMuDeItem = emrView.InsertDeItem({
                Index: "201",  // 数据元唯一ID
                Name: "皮疹及出血",  // 数据元名称
                Text: "有皮疹、皮下出血",  // 默认内容，注意设置默认内容后数据元的是否填写过值为true 如果想置为false，需要设置 AllocValue: "0"
                Frmtp: TDeFrmtp.Multiselect,  // 多选
                CMV: "272",  // 值域ID
                CMVVCode: "1,2",  // 选择的选项Code，以英文逗号分隔
                ItemMutex: "1",  // 多选时选项互斥
                MutexYes: "伴有",  // 多选选项互斥时，勾选的选项写回病历时统一增加的前缀
                MutexNo: "否认",  // 多选选项互斥时，未勾选的选项写回病历时统一增加的前缀
                ItemEditValue: "1"  // 选项值直接编辑，不通过弹出框处理
            });

            // 插入体温，用于演示异常值背景色的问题
            var vTempItem = emrView.insertDeItem({
                Index: "341",
                Name: "体温",
                Frmtp: TDeFrmtp.Number,
                Unit: "℃"
            });
        }

        function setReadOnly() {
            emrView.ReadOnly = !emrView.ReadOnly;
        }

        function applyTextStyle(style) {
            // 设置选中的文本设置样式
            emrView.ApplyTextStyle(style);
            //var bytes = new Uint8Array([46,0,104,0,99,0,102,0,52,0,46,0,49,0,4,71,0,0,0,0,0,0,0,2,1,0,0,0,2,0,0,128,63,0,0,0,0,0,0,0,0,0,0,0,0,255,192,192,192,0,3,1,2,0,0,0,0,0,40,65,4,0,139,91,83,79,0,255,0,0,0,0,255,255,255,0,0,64,65,4,0,139,91,83,79,0,255,0,0,0,0,255,255,255,1,253,1,0,0,0,0,0,0,1,0,1,28,0,0,0,0,0,0,0,9,0,0,0,0,0,82,67,0,128,148,67,0,0,200,65,0,0,200,65,0,0,160,65,0,0,160,65,1,1,1,20,0,0,0,24,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,24,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,116,1,0,0,0,0,0,0,4,0,0,0,1,0,0,0,0,0,0,0,1,0,10,0,0,0,89,151,9,129,224,101,242,102,32,95,0,0,24,0,106,0,73,0,110,0,100,0,101,0,120,0,61,0,52,0,57,0,57,0,13,0,10,0,78,0,97,0,109,0,101,0,61,0,89,151,9,129,242,102,32,95,13,0,10,0,70,0,114,0,109,0,116,0,112,0,61,0,82,0,83,0,13,0,10,0,67,0,77,0,86,0,61,0,50,0,57,0,57,0,13,0,10,0,67,0,77,0,86,0,86,0,67,0,111,0,100,0,101,0,61,0,49,0,13,0,10,0,1,0,0,0,0,0,0,0,0,0,4,0,0,0,32,0,32,0,0,0,8,0,0,0,1,0,0,0,0,0,0,0,0,0,30,0,0,0,89,151,9,129,242,102,32,95,8,255,9,103,242,102,32,95,207,99,240,143,64,136,65,109,185,101,17,84,9,255,0,0,24,0,106,0,73,0,110,0,100,0,101,0,120,0,61,0,52,0,57,0,57,0,13,0,10,0,78,0,97,0,109,0,101,0,61,0,89,151,9,129,242,102,32,95,13,0,10,0,70,0,114,0,109,0,116,0,112,0,61,0,77,0,83,0,13,0,10,0,67,0,77,0,86,0,61,0,50,0,57,0,57,0,13,0,10,0,67,0,77,0,86,0,86,0,67,0,111,0,100,0,101,0,61,0,50,0,13,0,10,0,1,0,0,0,0,0,0,0,0,0,32,0,0,0,32,0,32,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,51,0,0,0,8,0,0,0,0,0,0,0,0,0]);
            //emrView.LoadFromBytes(bytes);
        }

        function applyParaAlignHorz(align) {
            // 设置当前光标所在的段水平对齐
            emrView.ApplyParaAlignHorz(align);
        }

        function loadFromBytes(bytes) {  // 二进制数组
            // 加载文件，文件数据是byte数组
            emrView.LoadFromBytes(bytes);
        }

        function saveToBytes() {
            // 保存文件，返回文件数据的byte数组
            appendLine("saveToBytes存二进制文件");
            return emrView.SaveToBytes();
        }

        function saveToLiteBytes() {
            vBytes = emrView.SaveToLiteBytes();
            //emrView.InsertLiteBytes(vBytes);
        }

        function insertHyperLink() {
            emrView.InsertHyperLink({
                Text: "视频链接",
                HyperLink: "https://www.w3school.com.cn/i/movie.ogg"
            });
        }

        function insertDeItem() {
            // 插入数据元
            emrView.InsertDeItem({
                Index: "499",
                Name: "静脉曲张",
                Text: "静脉无曲张",
                //CMVVCode: "1",
                //Propertys: "Code=DE00.01.02.03\r\nXXX=xxx\r\nBBB=bbb",  // 也可以样一次性把自定义的属性添加进去
                // Propertys: {
                //     Code: "DE00.01.02.03",
                //     CMVVCode: "1"
                // },
                Frmtp: TDeFrmtp.Multiselect,
                CMV: "299"
            });

            //emrView.SetDeItemProperty("499", "Text", "2");
            //emrView.SetDeItemProperty("499", "EditProtect", "1");
            // emrView.SetDeItemProperty("499", "Propertys", {
            //     Code: "DE00.01.02.03",
            //     CMVVCode: "1",
            //     Text: "静脉无曲张"
            // });
        }

        function getDeItemText(index) {
            // 获取指定index的数据元的内容
            var vInfo = emrView.GetDeItemText(index);
            if (vInfo.result)  // 取到了
                appendLine("取到数据元内容:" + vInfo.text);  // 取到的内容
            else
                appendLine("未取到数据元内容");
        }

        function getDeItemProperty(index, propName) {
            // 获取指定index的数据元的指定属性内容
            var vInfo = emrView.GetDeItemProperty(index, propName);
            if (vInfo.result)  // 取到了
                appendLine("取到数据元属性:" + vInfo.text);  // 取到的内容
            else
                appendLine("未取到数据元属性内容");
        }

        function insertDeGroup(index, name) {
            // 插入数据组
            emrView.InsertDeGroup({
                Index: index,
                //Code: "DE00.01.02.03",
                //Propertys: "Code=DE00.01.02.03\r\nXXX=xxx\r\nBBB=bbb",  // 也可以样一次性把自定义的属性添加进去
                // Propertys: {
                //     Code: "DE00.01.02.03",
                //     CMVVCode: "1",
                //     Text: "静脉无曲张"
                // },
                Name: name
            });
        }

        function InsertDeControl() {
            emrView.InsertDeEdit({
                Index: "301",
                Name: "病历时间"
            });
        }

        function setDeGroupByText(index, s) {
            emrView.SetDeGroupByText(index, s);
        }

        function getDeGroupAsText(index) {
            appendLine(index + "数据组内容:" + emrView.GetDeGroupAsText(index));
        }

        var vBytes;
        function getDeGroupAsBytes(index) {
            vBytes = emrView.GetDeGroupAsBytes(index);
        }

        function setDeGroupByBytes(index) {
            if (!vBytes)
                return;

            emrView.SetDeGroupByBytes(index, vBytes);
        }

        function setProcDeGroupByText(index) {
            emrView.SetProcDeGroupByText(emrView.EditProcIndex, index, "text\r\n    bbb\r\nccccccccc");
        }

        function setProcDeGroupByBytes(index) {
            if (!vBytes)
                return;

            emrView.SetProcDeGroupByBytes(emrView.EditProcIndex, index, vBytes);
        }

        function setCaretDeGroupByText() {
            emrView.SetCaretDeGroupByText("text\r\n    bbb\r\nccccccccc");
        }

        function setCaretDeGroupByBytes() {
            if (!vBytes)
                return;

            emrView.SetCaretDeGroupByBytes(vBytes);
        }

        function insertDeImage(index, name) {
            // 仅插入空白占位图片，实际业务中再替换成相应的图片
            emrView.InsertDeImage({
                Index: index,
                Name: name,
                Width: 50,
                Height: 50,
                CanResize: false  // 不允许手动缩放改变大小
            });

            // 直接插入图片
            // getBase64ByUrl("./image/qm.png", function(base64) {
            //     emrView.InsertDeImage({
            //         Index: index,
            //         Name: name,
            //         Base64: base64,
            //         ImageType: "png",
            //         LoadedEvent: function () {
            //             console.log("插入图片加载完成！");
            //         }
            //     });
            // });
        }

        function setSignatureGraphic(index) {
            // 替换签名图片
            getBase64ByUrl("./image/qm.png", function(base64) {
                emrView.SetDeImage({
                    Index: index,
                    Base64: base64,
                    //Width: 150,
                    //Height: 100,
                    //AutoSize: true,  // 自动适应图片的大小
                    LoadedEvent: function () {
                        console.log("替换图片完成！");
                    }
                });
            });
        }

        /* 遍历编辑器中的数据元时，每遍历到一个数据元触发
        此方法参数使用编辑器内置的原生Item对象，注意相关的属性大小写
        */
        function traverseFun(data, itemNo, tag, domainStack, stop) {
            var vItem = data.Items[itemNo];
            if (vItem.StyleNo == TItemStyle.Domain) {  // 数据组
                if (vItem.IsProcBegin)
                    appendLine("病程开始--------唯一标识:" + vItem.Index);
                else if (vItem.IsProcEnd)
                    appendLine("病程结束--------唯一标识:" + vItem.Index);
                else if (vItem.MarkType == 0)
                    appendLine("数据组开始--------Index:" + vItem.Index);
                else
                    appendLine("数据组结束--------Index:" + vItem.Index);
            } else if (vItem.StyleNo > TItemStyle.Null) {  // 文本
                if (vItem.IsElement)
                    appendLine("数据元 Index:" + vItem.Index + " Text:" + vItem.Text);
                else
                    appendLine("自然文本 Text:" + vItem.Text);  // 原生Item文本属性Text(大写T开始)
            } else if (vItem.StyleNo == TItemStyle.CheckBox)
                appendLine("勾选框 Text:" + vItem.Text);
            else if (vItem.StyleNo == TItemStyle.Combobox)
                appendLine("下拉框 Text" + vItem.Text);
            else if (vItem.StyleNo == TItemStyle.Edit)
                appendLine("文本框 Text" + vItem.Text);
            else if (vItem.StyleNo == TItemStyle.DateTimePicker)
                appendLine("日期时间 Text" + vItem.Text);
            else if (vItem.StyleNo == TItemStyle.RadioGroup)
                appendLine("RadioGroup Text" + vItem.Text);
        }

        // 遍历编辑器中的数据元
        function traverseElement() {
            /*emrView.TraverseElement(fun, areas, tag)需要3个参数
            fun表示每遍历到一个元素时触发的事件
            areas是个集合，表示要遍历的文档区域，集合的成员是1:页眉、2:正文、4:页脚，areas为null时表示全部区域(正文，页眉，页脚)
            tag遍历标识，用于区域本次遍历是完成什么业务，可根据需要赋值
            */
            appendLine("开始遍历文档-----------------------------");
            var vAreas = new Set([]);
            vAreas.add(1);
            vAreas.add(2);
            vAreas.add(4);
            emrView.TraverseElement(traverseFun, vAreas, 0);
        }

        // 插入病程
        function insertProc(beforProcIndex) {
            getFileAsBytes("./file/首次病程记录.hcf", function(bytes) {
                if (bytes.length == 0)
                    return;

                // 病程时间，实际业务应该取服务端时间
                var vDate = new Date(); 
                var vDateTime = vDate.getFullYear() + (vDate.getMonth() + 1).toString()
                    + vDate.getDate() + vDate.getHours() + vDate.getMinutes() + vDate.getSeconds();
                
                // 病程属性，可添加病程控制相关的属性，每个属性是一个键值对，多个属性以\r\n分隔
                var vPropertys = TGroupProp.Name + "=首次病程记录\r\nuser=jt\r\ndt=" + vDateTime;  // 用户jt，日期vDateTime

                // 病程唯一ID，这里使用了当前时间，实际业务使用时可换为业务里的病程唯一ID生成规则
                var vProcIndex = vDateTime;

                // 在指定的病程(ID为vBeforProcIndex)前面插入新病程，如为""表示在最后插入病程
                var vBeforProcIndex = beforProcIndex ? beforProcIndex : "";

                var waitInfo = emrView.WaitMessage("正在加载病程...", function() {  // 创建一个等待提示
                    try {
                        console.time("创建病程");
                        emrView.BeginUpdate();  // 开启批量更新，提高效率
                        try {
                            emrView.ReadOnly = false;  // 病历切换为非只读
                            // 当前病历是否没有病程，即要插入的病程是否为整个病历的第一个病程
                            var vFirstProc = emrView.ProcCount == 0;

                            emrView.UndoDisenable();
                            try {
                                // 插入病程标识
                                if (emrView.InsertProc(vProcIndex, vPropertys, vBeforProcIndex)) {  // 插入病程标识成功
                                    appendLine("插入病程，标识为:" + vProcIndex);
                                    emrView.EditProcIndex = vProcIndex;  // 当前编辑的病程为新插入的病程
                                    if (vFirstProc) {  // 是整个病历的第一个病程
                                        emrView.LoadHeaderFromBytes(bytes, true);  // 加载页眉，同时加载边距信息
                                        emrView.LoadFooterFromBytes(bytes, false);  // 加载页脚，不加载边距信息
                                    }

                                    emrView.SetProcByFileSteam(vProcIndex, bytes);  // 设置当前病程的内容
                                }
                            } finally {
                                emrView.UndoEnable();
                            }
                        } finally {
                            emrView.EndUpdate();
                        }

                        emrView.ClearUndo();  // 清空撤销记录，防止用户把新插入的病程撤销了
                        emrView.ScrollToProc(emrView.EditProcIndex);  // 滚动到合适位置
                        console.timeEnd("创建病程");
                    } finally {
                        emrView.EndWaitMessage(waitInfo);  // 关闭等待提示
                    }
                });
            });
        }

        // 取指定Inex的病程内容
        function getProc() {
            //var text = emrView.GetProcAsText(procIndex);  // 返回病程内容文本
            //var bytes = emrView.GetProcAsBytes(procIndex);  // 返回病程内容Byte数组(二进制)
            var html = emrView.GetProcAsHtml(procIndex);  // 返回病程内容Html格式
            var vWindow = window.open("", "", "width=" + emrView.InnerView.ActiveSection.PaperWidthPix);
            vWindow.document.write(html);
            vWindow.focus();
        }

        // 编辑光标处病程
        function editCaretProc() {
            emrView.EditProcIndex = emrView.CaretProcInfo.Index;
        }

        // 删除光标处病程
        function deleteCaretProc() {
            emrView.DeleteProc(emrView.CaretProcInfo.Index);
        }

        // 取病程属性信息
        function getProcProperty() {
            var procIndex = document.getElementById("procIndex").value;
            // 取病程所有属性信息
            //appendLine("病程" + procIndex + "的属性信息:" + emrView.GetProcProperty(procIndex, TGroupProp.Propertys));
            // 取病程Name属性
            appendLine("病程" + procIndex + "的属性信息:" + emrView.GetProcProperty(procIndex, TGroupProp.Name));
        }

        // 开启关闭痕迹
        function setTrace() {
            emrView.Trace = !emrView.Trace;
            if (emrView.Trace)
                document.getElementById("btnTrace").innerHTML = "关闭留痕";
            else
                document.getElementById("btnTrace").innerHTML = "开启留痕";
        }

        function hideTrace() {
            //emrView.HideTrace = !emrView.HideTrace;
            var waitInfo = emrView.WaitMessage("正在加载病程...", function() {  // 创建一个等待提示
            });
        }

        // 在留痕模式下，对新痕迹添加痕迹信息
        function setTraceInfo() {
            // 痕迹时间，实际业务应该取服务端时间
            var vDate = new Date(); 
            var vDateTime = vDate.getFullYear() + "-" + (vDate.getMonth() + 1).toString()
                + "-" + vDate.getDate() + " " + vDate.getHours() + ":" + vDate.getMinutes() + ":" + vDate.getSeconds();
            var vDeItem;

            if (emrView.Trace) {  // 当前是留痕模式
                var vAreas = new Set([]);
                vAreas.add(2);
                emrView.TraverseElement(
                    function (data, itemNo, tag, domainStack, stop) {
                        vDeItem = data.Items[itemNo];
                        if (vDeItem.StyleNo > -1) {  // 是文本
                            if (vDeItem.TraceStyles.value != 0) {
                                if (vDeItem.TraceStyles.has(TDeTraceStyle.Add) &&
                                    vDeItem.GetValue(TDeProp.TraceAdd) == "")
                                {
                                    // 新的添加痕迹
                                    vDeItem.SetValue(TDeProp.TraceAddLevel, TDeTraceLevel.Two);  // 痕迹的医师级别，不需要可以不赋值
                                    vDeItem.SetValue(TDeProp.TraceAdd, "荆通(jt " + vDateTime + ")添加");
                                }

                                if (vDeItem.TraceStyles.has(TDeTraceStyle.Del) &&
                                    vDeItem.GetValue(TDeProp.TraceDel) == "")
                                {
                                    // 新的删除痕迹
                                    vDeItem.SetValue(TDeProp.TraceDelLevel, TDeTraceLevel.Two);  // 痕迹的医师级别，不需要可以不赋值
                                    vDeItem.SetValue(TDeProp.TraceDel, "荆通(jt " + vDateTime + ")删除");
                                }
                            }
                        }
                    }, 
                    vAreas, 0);
            } else
                appendLine("当前不是留痕模式");
        }

        function resetEmrView() {
            //emrView.Dispose();
            //emrView = null;
            //load();
            emrEdit = new THCEmrEditLib({});
        }

        function activeTableInsertRowContentAfter() {
            emrView.InnerView.ActiveTableInsertRowContentAfter({
                Rows: [  // 行s
                    {  // 第1行
                        Cells: [  // 列s
                            {  // 第1列
                                Text: "新增1x1"
                            },
                            {

                            },
                            {
                                Text: "新增1x3"
                            }
                        ]
                    },

                    {

                    },

                    {
                        Cells: [
                            {
                                Text: "新增3x1"
                            }
                        ]
                    }
                ]
            });
        }
    </script>
</head>

<body style="height: 100%;" onload="load()">
    <textarea id="textBox" style="height: 150px; width: 860px;"></textarea>
    <br/>
    <button type="button" onclick="setReadOnly()">只读/编辑</button>
    <button type="button" onclick="applyTextStyle(1)">加粗</button>
    <button type="button" onclick="applyParaAlignHorz(2)">右对齐</button>
    <button type="button" onclick="insertHyperLink()">插入链接</button>
    <button type="button" onclick="insertDeItem()">插入数据元</button>
    <button type="button" onclick="getDeItemText('495')">取数据元内容</button>
    <button type="button" onclick="insertDeGroup('1082', '主诉')">插入数据组</button>
    <button type="button" onclick="getDeGroupAsText('1082')">取数据组内容(文本)</button>
    <button type="button" onclick="setDeGroupByText('1082', '这是通过事件设置的数据内容')">设置数据组内容(文本)</button>
    <br/>
    <button type="button" onclick="getDeGroupAsBytes('1082')">取数据组内容(bytes)</button>
    <button type="button" onclick="setDeGroupByBytes('1082')">设置数据组内容(bytes)</button>
    <button type="button" onclick="setProcDeGroupByText('1082')">设置病程数据组内容(文本)</button>
    <button type="button" onclick="setProcDeGroupByBytes('1082')">设置病程数据组内容(bytes)</button>
    <button type="button" onclick="setCaretDeGroupByText()">设置光标处数据组内容(文本)</button>
    <button type="button" onclick="setCaretDeGroupByBytes()">设置光标处数据组内容(bytes)</button>
    <br/>
    <button type="button" onclick="insertDeImage('1600', '主治医师')">插入签名图片</button>
    <button type="button" onclick="setSignatureGraphic('1600')">替换签名图片</button>
    <button type="button" onclick="insertProc()">插入病程</button>
    <input id="procIndex" type="text" value="输入病程唯一标识">
    <button type="button" onclick="getProc()">取病程内容</button>
    <button type="button" onclick="getProcProperty()">取病程属性</button>
    <button type="button" onclick="editCaretProc()">编辑光标处病程</button>
    <button type="button" onclick="deleteCaretProc()">删除光标处病程</button>
    <br/>
    <button id="btnTrace" type="button" onclick="setTrace()">开启留痕</button>
    <button type="button" onclick="setTraceInfo()">设置痕迹信息</button>
    <button id="btnTrace" type="button" onclick="hideTrace()">不显示痕迹</button>
    <button type="button" onclick="resetEmrView()">释放和重新创建编辑器</button>
    <button type="button" onclick="activeTableInsertRowContentAfter()">表格光标所在行后添加行</button>
    <button type="button" onclick="InsertDeControl()">插入控件</button>
    <button type="button" onclick="saveToBytes()">保存(二进制)</button>
    <button type="button" onclick="saveToLiteBytes()">保存为片断(二进制)</button>
    <button type="button" onclick="traverseElement()">遍历元素</button>
    <div id="divHCEmrView" style="left: 20px; top: 270px; position: fixed; width: 860px; height: 600px; background: lightgray;"></div>
</body>

</html>